﻿using System;
using System.Collections.Generic;

using PostSharp.Aspects;
using PostSharp.Reflection;

using ReflectSoftware.Insight;

namespace ReflectSoftware.Insight.Extensions.PostSharp
{
    public enum RITraceFieldDispatchType
    {
        Log,
        Scratchpad,        
        Both
    }
    
    [Serializable]
    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
    public class RITraceFieldAttribute : LocationInterceptionAspect
    {
        private readonly String ExtensionName;
        private readonly RITraceFieldDispatchType DispatchType;
        private ReflectInsight ReflectInsightInstance;
        private String Label;
                
        //----------------------------------------------------------------------
        public RITraceFieldAttribute(String extension, String label, RITraceFieldDispatchType dispatchType)
        {
            ExtensionName = extension ?? String.Empty;
            DispatchType = dispatchType;
            Label = label ?? String.Empty;
        }
        //----------------------------------------------------------------------
        public RITraceFieldAttribute(String extension, String label): this(extension, label, RITraceFieldDispatchType.Scratchpad)
        {
        }
        //----------------------------------------------------------------------
        public RITraceFieldAttribute(String extension): this(extension, String.Empty)
        {
        }
        //----------------------------------------------------------------------
        public override void CompileTimeInitialize(LocationInfo targetLocation, AspectInfo aspectInfo)
        {
            base.CompileTimeInitialize(targetLocation, aspectInfo);            
                        
            if (Label.Trim() == String.Empty)
                Label = targetLocation.FieldInfo.Name;
        }        
        //----------------------------------------------------------------------
        public override void RuntimeInitialize(LocationInfo locationInfo)
        {
            base.RuntimeInitialize(locationInfo);

            OnConfigFileChange();
            RIEventManager.OnServiceConfigChange += OnConfigFileChange;
        }
        //---------------------------------------------------------------------
        protected void OnConfigFileChange()
        {
            try
            {
                lock (this)
                {
                    String instanceName = ReflectInsightConfig.Settings.GetExtensionAttribute(ExtensionName, "instance", String.Empty);
                    ReflectInsightInstance = RILogManager.Get(instanceName) ?? RILogManager.Default;
                }
            }
            catch (Exception ex)
            {
                RIExceptionManager.Publish(ex, "Failed during: RITraceFieldAttribute.OnConfigFileChange()");
            }
        }
        //----------------------------------------------------------------------
        public override void OnSetValue(LocationInterceptionArgs args)
        {
            base.OnSetValue(args);

            switch(DispatchType)
            {
                case RITraceFieldDispatchType.Scratchpad:
                    ReflectInsightInstance.ViewerSendScratchpad(Label, args.Value);
                    break;

                case RITraceFieldDispatchType.Log:
                    ReflectInsightInstance.SendTrace("{0} = {1}", Label, args.Value);
                    break;

                default:
                    ReflectInsightInstance.ViewerSendScratchpad(Label, args.Value);
                    ReflectInsightInstance.SendTrace("{0} = {1}", Label, args.Value);
                    break;
            }
        }
    }
}
